package vip.meeet.jdk.mem;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.ArrayList;

/**
 * -XX:PermSize=10M -XX:MaxPermSize=10M
 *
 * 移除永久代的工作从JDK1.7就开始了。JDK1.7中，存储在永久代的部分数据就已经转移到了Java Heap或者是 Native Heap。
 * 但永久代仍存在于JDK1.7中，并没完全移除，譬如：
 * 符号引用(Symbols)转移到了native heap；
 * 字面量(interned strings)转移到了java heap；
 * 类的静态变量(class statics)转移到了java heap
 * -XX:MetaspaceSize
 * -XX:MaxMetaspaceSize
 * -XX:MinMetaspaceFreeRatio
 * -XX:MaxMetaspaceFreeRatio
 *
 * 元空间并不在虚拟机中，而是使用本地内存
 */
public class ConstantPoolOOM {

    public static void main(String[] args) {
//        internMethod();
        constantPoolLeak();
//        cglib();
    }

    /**
     * 方法区溢出
     */
    private static void constantPoolLeak(){
        ArrayList<String> strings = new ArrayList<>();
        int i = 0;
        while (i<Integer.MAX_VALUE){
            strings.add(String.valueOf(i++).intern());
        }
    }

    /**
     * intern:
     * 1.6: 首次遇到复制字符串到永久代
     * 1.7: 在常量池中记录首次出现实例的引用
     */
    private static void internMethod(){
        String s1 = new StringBuffer("计算机").append("软件").toString();
        String s2 = new StringBuffer("ja").append("va").toString();
        System.out.println(s1.intern() == s1);
        System.out.println(s2.intern() == s2);
    }

    private static void cglib(){
        while (true){
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(OOMObject.class);
            enhancer.setUseCache(false);
            enhancer.setCallback(new MethodInterceptor() {
                @Override
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    return methodProxy.invokeSuper(o,objects);
                }
            });
            enhancer.create();
        }
    }

    static class OOMObject{

    }
}
